home *** CD-ROM | disk | FTP | other *** search
/ NetNews Offline 2 / NetNews Offline Volume 2.iso / news / comp / lang / c++-part1 / 8215 < prev    next >
Encoding:
Internet Message Format  |  1996-08-05  |  3.6 KB

  1. Path: stc06.ctd.ornl.gov!msr!kennel
  2. From: kennel@msr.epm.ornl.gov (Matt Kennel)
  3. Newsgroups: comp.lang.c++,
  4. Subject: Re: Tough FACTORIAL math problem...
  5. Followup-To: comp.lang.c++,
  6. Date: 15 Feb 1996 19:58:43 GMT
  7. Organization: Oak Ridge National Lab, Oak Ridge, TN
  8. Message-ID: <4g039j$a3l@stc06.ctd.ornl.gov>
  9. References: <4fr8be$ass@news.iconn.net> <31224679.6193@born.com> <4fvp9v$sso@newsroom.hitc.com>
  10. NNTP-Posting-Host: msr.epm.ornl.gov
  11. X-Newsreader: TIN [version 1.2 PL2]
  12.  
  13. G. Patrick Sand (psand@eos.hitc.com) wrote:
  14. > In article <31224679.6193@born.com>, clelaj@born.com says...
  15. > >
  16. > >The Crow wrote:
  17. > >> 
  18. > >> Here is what I am trying to do, I want to find the last NON-ZERO digit
  19. > > of a
  20. > >> given factorial.  For instance,
  21. > >> 
  22. > >> 5! = 120
  23. > >> 
  24. > >> so the last non-zero digit is 2.  I want to be able to do this up to 1
  25. > >000.
  26. > [SNIP!!!]
  27.  
  28. > Here are two other approaches, which should take up very little space and 
  29. > be lightning quick:
  30.  
  31. > Since you only care about the smallest non-zero digit, just multiply the 
  32. > last smallest non-zero digit by the next number's smallest non-zero 
  33. > digit!
  34. > You can easily test for the result being a multiple of 10.  This requires 
  35. > a bit of bookkeeping for dealing with numbers like 10, 100,
  36. > 200, 350, etc. but that's fairly easy to handle...Heck, you could write 
  37. > three nested for(...) loops to handle going from 1-1000, although some 
  38. > purists will balk...
  39.  
  40. > If you want to minimize the testing for zero-digits, build yourself a 9x9 
  41. > matrix which holds the least-significant digit of the product of 
  42. > (i+1)*(j+1)
  43. > [i,j are C/C++ indexes ranging from 0-8].  You then can use three nested 
  44. > for(...) loops and just select the row (new number lsd) and column (lsd 
  45. > of previous factorial) and look it up...
  46.  
  47. > The nice thing with the second approach is that it can be easily modified 
  48. > to do this in MOD J, where J is not 10.  Just adjust the for(...) loops 
  49. > to range between 0 and J-1 and have the matrix be (J-1)x(J-1) big...You 
  50. > just pay for the looping and lookup time, but you don't have to multiply 
  51. > things and divide...
  52.  
  53. I don't know if this is the *fastest* way, but it looks like it
  54. should work and it's easy to understand. 
  55.  
  56. 1000! = 1000 * 999 * 998 * 997 ... *3 * 2 * 1
  57.  
  58. For each factor, f_i, express as 2^m_i * 5^n_i * p_i .
  59.  
  60. where p_i is divisible by neither 2 nor 5. 
  61.  
  62. Now, out front, collect as many factors of 2*5 (i.e. 10) you can.
  63.  
  64. 1000! = (10)^N * 2^m * 5^n * p_1000 * p_999 * p_998 ... *p_3 * p_2 * p_1
  65.  
  66. One or both of m or n will be zero .
  67.  
  68. Take off 10^N and multiply the remaining terms using arithmetic modulo 10. 
  69.  
  70. By keeping a running loop you should be able to do this in O(1) space and 
  71. O(n) time for n!.   Through the loop, take out as many factors of 2 and
  72. 5 you can, and save that number.  Multiply the remaining factors modulo 10.
  73. When you're done with those, see how many 2's and 5's you have left. 
  74. Make as many 10's as you can with them, discard them, and multiply the 
  75. running number by either the remaining 2's or the remaining 5's, again modulo
  76. 10.  The final answer should be "the last nonzero digit of n!". 
  77.  
  78. tell me if I'm wrong.
  79.  
  80. I still feel like there's some elementary number theory that I'm missing
  81. like
  82.  
  83. N mod p1*p2 = ??? mod p1 * ??? mod p2?
  84.  
  85. that would simplify things more
  86.  
  87. cheers
  88. Matt
  89.  
  90. > Hope this helps...
  91. > -- 
  92. > G. Patrick Sand
  93. > psand@eos.hitc.com
  94. > PatSand@aol.com
  95. > (301) 925-0791
  96. > "Travel Light But Right..."
  97. > Microsoft Network is prohibited from redistributing 
  98. > this work in any form, in whole or in part.   License 
  99. > to distribute this individual post is available to Microsoft
  100. > for $999. Posting without permission constitutes an 
  101. > agreement to these terms...gps
  102.  
  103.